package dao

import (
	"context"
	"errors"
	"github.com/qiniu/qmgo"
	"github.com/sirupsen/logrus"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/bson/primitive"
	"go.mongodb.org/mongo-driver/mongo"
	"monoblog/config"
	"monoblog/domain/dto"
	"monoblog/domain/model"
	"sync"
)

var (
	commentRepo *CommentRepository // 单例实例存储变量
	once3       sync.Once          // 确保初始化只执行一次的同步工具
)

// 初始化 QMGO 集合（单例模式）
func NewCommentRepository() *CommentRepository {
	once3.Do(func() { // 并发安全的初始化逻辑，只会执行一次
		commentRepo = &CommentRepository{
			collection: config.GetDataBase().Collection(model.CommentCollectionName), //指定集合名称
			ctx:        context.Background(),
		}
	})
	return commentRepo // 返回唯一实例
}

type CommentRepository struct {
	collection *qmgo.Collection // QMGO 集合对象（替代原生 mongo.Collection）
	ctx        context.Context  // 上下文（用于数据库操作超时控制）
}

// Add - 新增评论
func (impl *CommentRepository) Add(comment *model.Comment) error {
	r, err := impl.collection.InsertOne(impl.ctx, comment)
	if oid, ok := r.InsertedID.(primitive.ObjectID); ok {
		comment.ID = oid.Hex()
	}
	return err
}

// UpdateStatus - 按 ID 更新评论状态
func (impl *CommentRepository) UpdateStatus(id string, status model.CommentStatus) error {
	keyId, _ := primitive.ObjectIDFromHex(id)

	// 使用$set操作符实现字段更新
	updateDoc := bson.M{"$set": bson.M{"status": status.Value()}}
	err := impl.collection.UpdateId(impl.ctx, keyId, updateDoc)
	return err
}

// UpdateLikeCount 更新点赞数 递增±1
func (impl *CommentRepository) UpdateLikeCount(id string, delta int) error {
	keyId, _ := primitive.ObjectIDFromHex(id)

	// 使用$inc操作符实现字段自增1
	updateDoc := bson.M{"$inc": bson.M{"likeCount": delta}}
	err := impl.collection.UpdateId(impl.ctx, keyId, updateDoc)
	return err
}

// FindByID 根据ID查询评论
func (impl *CommentRepository) FindByID(id string) (*model.Comment, error) {
	keyId, _ := primitive.ObjectIDFromHex(id)

	var comment model.Comment
	err := impl.collection.Find(impl.ctx, qmgo.M{"_id": keyId}).One(&comment)

	if errors.Is(err, mongo.ErrNoDocuments) {
		logrus.Warnf("record not found. id: %v", id)
		return nil, errors.New("找不到数据, id: " + id)
	}
	return &comment, err
}

// FindList - 按条件查询评论列表
func (impl *CommentRepository) FindList(query dto.CommentQuery) ([]*model.Comment, int, error) {
	var comments = make([]*model.Comment, 0)

	filter := bson.M{} // 构建查询条件：空条件

	err := impl.collection.Find(impl.ctx, filter).Sort("-createTime").All(&comments)
	return comments, 0, err
}

// FindSubListByRootId 查询根评论的子评论list
func (impl *CommentRepository) FindSubListByRootId(rootId string) ([]*model.Comment, error) {
	var comments = make([]*model.Comment, 0)

	// 查询条件：rootId 匹配
	filter := bson.M{
		"rootId": rootId,
		"status": model.COMMENT_OPENED.Value(),
	}
	err := impl.collection.Find(impl.ctx, filter).Sort("createTime").All(&comments)

	return comments, err
}

// FindRootListByBlogId 查询文章的根评论list
func (impl *CommentRepository) FindRootListByBlogId(blogId string) ([]*model.Comment, int, error) {
	var comments = make([]*model.Comment, 0)

	// 查询条件：blogId 匹配且为根评论（假设根评论的 rootId 为空或自身ID）
	filter := bson.M{
		"blogId": blogId,
		"rootId": bson.M{"$exists": false},
		"status": model.COMMENT_OPENED.Value(),
	}
	err := impl.collection.Find(impl.ctx, filter).Sort("createTime").All(&comments)

	return comments, 0, err
}
